#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<semaphore.h>
#include<pthread.h>
//单生产单消费
//多生产多消费
//生产消费互斥同步
//生产和生产互斥--同步
//消费和消费互斥--同步
//加锁
template<typename T>
class RingQueue
{
    private:
    void P(sem_t &sem)//等待
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);//对信号量++
    }
    void Lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t &mutex)
    {
        pthread_mutex_unlock(&mutex);
    }

    public:
    RingQueue(int cap)
        :_ring_queue(cap)
        ,_capacity(cap)
        ,_productor_step(0)
        ,_consumer_step(0)
    {
        //对生产者信号和消费者信号初始化
        sem_init(&sem_room_sem,0,_capacity);
        sem_init(&sem_data_sem,0,0);
        //互斥初始化
        pthread_mutex_init(&_productor_mutex,nullptr);
        pthread_mutex_init(&_consumer_mutex,nullptr);

    }
    void Enqueue(const T &in)
    {
        //生产
         P(sem_room_sem);
         Lock(_productor_mutex);
         //要由空间
         _ring_queue[_productor_step++] = in;
         _productor_step %=_capacity;//成环
        Unlock(_productor_mutex);
        V(sem_data_sem);
    }

    void Pop(T *out)
    {
        //消费
        P(sem_data_sem);
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step];
        _consumer_step%=_capacity;
        Unlock(_consumer_mutex);
        V(sem_room_sem);
    }
    ~RingQueue()
    {
            sem_destroy(&sem_room_sem);
            sem_destroy(&sem_data_sem);

            pthread_mutex_destroy(&_productor_mutex);
            pthread_mutex_destroy(&_consumer_mutex);
    }
    private:
    //1:环形队列
    std::vector<T> _ring_queue;
    int _capacity;//容量上限
    //生产者和消费者下标
    int _productor_step;
    int _consumer_step;
    //定义信号量
    sem_t sem_room_sem;//生产者关注的通量
    sem_t sem_data_sem;//消费关注数据

    //生产者和消费者互斥关系
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};